﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DingTalkByHttp.Helper
{
    /// <summary>
    /// HTTP访问类
    /// </summary>
    public class HttpRequestUntil
    {

        private string contentType = string.Empty;

        public HttpRequestUntil() { }

        public HttpRequestUntil(string method, string contentType)
        {
            this.Method = method;
            this.contentType = contentType;
        }
        /// <summary>
        /// 不校验Https证书的合法性
        /// </summary>
        public bool NotVerifyCertificate { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="responseContents"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public string Response(string url, string responseContents, int? timeout = null)
        {
            string returnData;
            //读取响应流
            StreamReader reader = null;
            HttpWebResponse response = null;
            Stream stream = null;
            try
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("错误：没有设置URL地址");
                }
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                if (NotVerifyCertificate)
                {
                    request.ServerCertificateValidationCallback += RemoteCertificateVakidate;
                }
                request.Method = Method;
                request.ContentType = contentType;
                request.ServicePoint.Expect100Continue = false;
                if (timeout.HasValue)
                {
                    request.Timeout = timeout.Value;
                }
                else
                {
                    request.Timeout = 600000;
                }
                //如果需要POST数据
                if (request.Method.Equals("POST"))
                {
                    using (stream = request.GetRequestStream())
                    {
                        byte[] data = Encoding.UTF8.GetBytes(responseContents);
                        stream.Write(data, 0, data.Length);
                    }
                }
                //获取响应，并设置响应编码
                response = (HttpWebResponse)request.GetResponse();
                string encoding = response.ContentEncoding;
                if (encoding == null || encoding.Length < 1)
                {
                    encoding = "UTF-8"; //默认编码
                }
                //读取响应流
                reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
                returnData = reader.ReadToEnd();
            }
            catch (WebException ex)
            {
                throw new Exception(ex.Message);
            }
            catch (Exception ex)
            {
                returnData = ex.Message;
            }
            finally
            {
                if (stream != null)
                {
                    stream.Dispose();
                    stream.Close();
                }
                if (reader != null)
                {
                    reader.Dispose();
                    reader.Close();
                }
                if (response != null)
                {
                    response.Dispose();
                    response.Close();
                }
            }
            return returnData;
        }
        /// <summary>
        /// 根据URL获取文件流
        /// </summary>
        /// <param name="url"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public byte[] getFileByte(string url, string contentType = "")
        {
            if (url.Contains("https"))
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            }
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.UserAgent = _userAgent;
            request.Credentials = CredentialCache.DefaultCredentials;
            request.Method = _method;

            request.KeepAlive = false;
            request.AllowAutoRedirect = false;
            request.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
            request.ProtocolVersion = HttpVersion.Version10;
            request.ContentLength = 0;
            HttpWebResponse response;
            response = (HttpWebResponse)request.GetResponse();
            if (!string.IsNullOrEmpty(contentType) && !response.ContentType.Contains(contentType))
            {
                throw new Exception("附件下载异常");
            }
            Stream resStream;
            resStream = response.GetResponseStream();
            MemoryStream memoryStream = new MemoryStream(); //将返回流转置成内存流  解决返回网络流长度为-1的问题
            const int bufferLength = 1024;
            int actual;
            byte[] buffer = new byte[bufferLength];
            while ((actual = resStream.Read(buffer, 0, bufferLength)) > 0)
            {
                memoryStream.Write(buffer, 0, actual);
            }
            memoryStream.Position = 0;
            //读取流中的内容
            int count = (int)memoryStream.Length;
            int offset = 0;
            byte[] buf = new byte[count];
            while (count > 0)
            {
                int n = memoryStream.Read(buf, offset, count);
                if (n == 0)
                    break;
                count -= n;
                offset += n;
            }
            memoryStream.Close();
            memoryStream.Dispose();
            return buf;
        }

        private bool RemoteCertificateVakidate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }
        public string GetHttpContext(string url, int? timeout = null)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = _method; //请求方法
            req.Accept = _accept; //接受的内容
            req.UserAgent = _userAgent; //用户代理
            if (timeout.HasValue)
            {
                req.Timeout = timeout.Value;
            }
            else
            {
                req.Timeout = 1000 * 60 * 10;
            }
            var hettpResponse = (HttpWebResponse)req.GetResponse();
            Stream respStream = hettpResponse.GetResponseStream();
            StreamReader respStreamReader = new StreamReader(respStream, Encoding.UTF8);
            var context = respStreamReader.ReadToEnd();
            return context;
        }

        public void DownFile(string url, string path, string fileName, string contentType = "")
        {
            if (url.Contains("https"))
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
            }
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.UserAgent = _userAgent;
            request.Credentials = CredentialCache.DefaultCredentials;
            request.Method = _method;

            request.KeepAlive = false;
            request.AllowAutoRedirect = false;
            request.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
            request.ProtocolVersion = HttpVersion.Version10;
            request.ContentLength = 0;
            HttpWebResponse response;
            response = (HttpWebResponse)request.GetResponse();
            if (!string.IsNullOrEmpty(contentType) && !response.ContentType.Contains(contentType))
            {
                throw new Exception("附件下载异常");
            }

            Stream resStream;
            resStream = response.GetResponseStream();
            MemoryStream memoryStream = new MemoryStream(); //将返回流转置成内存流  解决返回网络流长度为-1的问题
            const int bufferLength = 1024;
            int actual;
            byte[] buffer = new byte[bufferLength];
            while ((actual = resStream.Read(buffer, 0, bufferLength)) > 0)
            {
                memoryStream.Write(buffer, 0, actual);
            }
            memoryStream.Position = 0;
            //读取流中的内容
            int count = (int)memoryStream.Length;
            int offset = 0;
            byte[] buf = new byte[count];
            while (count > 0)
            {
                int n = memoryStream.Read(buf, offset, count);
                if (n == 0)
                    break;
                count -= n;
                offset += n;
            }
            memoryStream.Close();
            memoryStream.Dispose();
            //判断文件夹是否存在
            if (!File.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            //下载文件
            FileStream fs = new FileStream(path + "\\" + fileName, FileMode.Create, FileAccess.Write);
            fs.Write(buf, 0, buf.Length);
            fs.Flush();
            fs.Close();
            fs.Dispose();
            Thread.Sleep(2000);
        }




        #region Method
        private string _method = "Get";
        /// <summary>
        /// 默认Get
        /// </summary>
        public string Method
        {
            get
            {
                return _method;
            }
            set
            {
                _method = value;
            }
        }
        #endregion
        #region Accept
        private string _accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";

        public string Accept { get { return _accept; } set { _accept = value; } }
        #endregion
        #region UserAgent
        private string _userAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
        public string UserAgent { get { return _userAgent; } set { _userAgent = value; } }
        #endregion

        public string GetHttpContentTypeByFile(string fileName)
        {
            var extension = Path.GetExtension(fileName);
            if (string.IsNullOrEmpty(extension))
            {
                return "";
            }
            switch (extension.ToUpper().Replace(".", ""))
            {
                case "PDF":
                    return "application/pdf";
                case "XLS":
                    return "application/vnd.ms-excel";
                case "DOC":
                    return "application/msword";
                default:
                    return "";
            }
        }
    }
}
